package com.xfdmao.fcat.coin.huobi.util;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xfdmao.fcat.coin.huobi.contract.api.HbdmClient;
import com.xfdmao.fcat.coin.huobi.contract.api.HbdmRestApiV1;
import com.xfdmao.fcat.coin.huobi.contract.api.IHbdmRestApi;
import com.xfdmao.fcat.coin.huobi.globle.response.Kline;
import org.apache.http.HttpException;
import org.apache.log4j.Logger;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * Created by Administrator on 2019/7/29.
 */
public class StrategyUtil {
    private static Logger logger = Logger.getLogger(StrategyUtil.class);

    private static int avgUpDownFlagOrder = 0;//持仓状态，0：未知；1：持仓中，-1：空仓

    /**
     *  站上均线买入，跌破均线卖出
     * @throws Exception
     */
    public static void avgUpDown() throws Exception{
        String symbol = "BTC";//交易对
        String contractType = "quarter";//合约类型
        int ma = 20;//均线
        String period = "15min";//时间周期
        int leverRate = 20;//合约倍数
        int volume = 2;//每次买卖的张数
        /**
         * get请求无需发送身份认证,通常用于获取行情，市场深度等公共信息
         */
        String api_key = HbdmClient.api_key; // huobi申请的apiKey,API调试过程中有问题或者有疑问可反馈微信号shaoxiaofeng1118
        String secret_key = HbdmClient.secret_key; // huobi申请的secretKey
        String url_prex = HbdmClient.url_prex;//"https://api.hbdm.com";//火币api接口地址https://api.hbdm.com
        IHbdmRestApi futureGetV1 = new HbdmRestApiV1(url_prex);
        IHbdmRestApi futurePostV1 = new HbdmRestApiV1(url_prex, api_key, secret_key);
        initAvgUpDown(futurePostV1,symbol,contractType);
        logger.info("avgUpDownFlagOrder：" +avgUpDownFlagOrder);
        // 获取K线数据
        String historyKline = futureGetV1.futureMarketHistoryKline(symbol+"_CQ", period,ma+"");
        logger.info("获取K线数据" + historyKline);
        JSONObject jsonObject = JSONObject.parseObject(historyKline);
        JSONArray jsonArray = jsonObject.getJSONArray("data");
        List<Kline> klines = jsonArray.toJavaList(Kline.class);
        KlineUtil.sort(klines);
        logger.info("K线排序：" +JSONObject.toJSONString(klines));
        double avg = KlineUtil.queryAvg(klines);
        logger.info("均值：" + avg);
        double priceLastKlineClose = klines.get(1).getClose();
        logger.info("上一个已收盘的K线：" + JSONObject.toJSONString(klines.get(1)));
        double priceLatestClose = klines.get(0).getClose();
        logger.info("最新价："+priceLatestClose);
        if(priceLastKlineClose>avg && priceLatestClose>avg) { //站上均线
            if(avgUpDownFlagOrder == -1){
                buyOpen(symbol, contractType, leverRate, volume, futurePostV1);
            }
        }
        if(priceLastKlineClose<avg && priceLatestClose<avg){ //跌破均线
            if(avgUpDownFlagOrder == 1){
                sellClose(symbol, contractType, leverRate, volume, futurePostV1);
            }
        }
    }

    /**
     * 初始化数据，查看是否持仓
     * @param futurePostV1
     * @param symbol
     * @param contractType
     * @throws HttpException
     * @throws IOException
     */
    private static void initAvgUpDown(IHbdmRestApi futurePostV1,String symbol,String contractType) throws HttpException, IOException {
        String positionInfo = futurePostV1.futureContractPositionInfo(symbol);
        logger.info("获取用户持仓信息" + positionInfo);
        JSONObject jsonObject = JSONObject.parseObject(positionInfo);
        String status = jsonObject.getString("status");
        if("ok".equals(status)){
            JSONArray jsonArray = jsonObject.getJSONArray("data");
            if(jsonArray==null || jsonArray.size()==0){
                avgUpDownFlagOrder=-1;
            }else{
                for(int i=0;i<jsonArray.size();i++){
                    JSONObject jsonObject1 = jsonArray.getJSONObject(i);
                    if(symbol.equals(jsonObject1.getString("symbol")) && contractType.equals(jsonObject1.getString("contract_type"))){
                        avgUpDownFlagOrder=1;
                    }else{
                        avgUpDownFlagOrder = -1;
                    }
                }
            }
        }
    }

    /**
     * 两天均线策略BTC
     */
    public static void towMaBTC()  throws Exception{
        String symbol = "BTC";//交易对
        String contractType = "quarter";//合约类型
        int upMa = 30;//建仓均线
        int downMa = 9;//平仓均线
        String period = "15min";//时间周期
        int leverRate = 20;//合约倍数
        int volume = 2;//每次买卖的张数
        double upperLeadFactor = 8.0;  //上引线的判断因子
        /**
         * get请求无需发送身份认证,通常用于获取行情，市场深度等公共信息
         */
        String api_key = HbdmClient.api_key; // huobi申请的apiKey,API调试过程中有问题或者有疑问可反馈微信号shaoxiaofeng1118
        String secret_key = HbdmClient.secret_key; // huobi申请的secretKey
        String url_prex = HbdmClient.url_prex;//"https://api.hbdm.com";//火币api接口地址https://api.hbdm.com
        IHbdmRestApi futureGetV1 = new HbdmRestApiV1(url_prex);
        IHbdmRestApi futurePostV1 = new HbdmRestApiV1(url_prex, api_key, secret_key);
        initAvgUpDown(futurePostV1,symbol,contractType);
        logger.info("avgUpDownFlagOrder：" +avgUpDownFlagOrder);
        // 获取K线数据
        String historyKline = futureGetV1.futureMarketHistoryKline(symbol+"_CQ", period,(upMa+2)+"");
        logger.info("获取K线数据" + historyKline);
        JSONObject jsonObject = JSONObject.parseObject(historyKline);
        JSONArray jsonArray = jsonObject.getJSONArray("data");
        List<Kline> klines = jsonArray.toJavaList(Kline.class);
        KlineUtil.sort(klines);
        logger.info("K线排序,时间最大的排前面：" +JSONObject.toJSONString(klines));

        List<Kline> klinesUp = new ArrayList<>();
        for(int i=0;i<upMa;i++){
            klinesUp.add(klines.get(i+1));
        }
        double upAvg = KlineUtil.queryAvg(klines); //当前收盘K线的长期均线的值

        List<Kline> klinesDown = new ArrayList<>();
        for(int i=0;i<downMa;i++){
            klinesDown.add(klines.get(i+1));
        }
        double downAvg = KlineUtil.queryAvg(klinesDown);   //当前收盘K线的短期均线的值

        List<Kline> klinesUpPrevious = new ArrayList<>();
        for(int i=0;i<upMa;i++){
            klinesUpPrevious.add(klines.get(i+2));
        }
        double upAvgPrevious = KlineUtil.queryAvg(klinesUpPrevious);    //上一根收盘K线的长期均线的值

        List<Kline> klinesDownPrevious = new ArrayList<>();
        for(int i=0;i<downMa;i++){
            klinesDownPrevious.add(klines.get(i+2));
        }
        double downAvgPrevious = KlineUtil.queryAvg(klinesDownPrevious);  //上一根收盘K线的短期均线的值

        logger.info("均值upMA：" + upAvg);
        logger.info("均值downMA：" + downAvg);
        double priceLastKlineClose = klines.get(1).getClose();
        logger.info("上一个已收盘的K线：" + JSONObject.toJSONString(klines.get(1)));
        if(
                upAvg < downAvg  &&    //买入条件： 1、当前收盘K线的长期均线值 小于 短期均线的值
                upAvgPrevious > downAvgPrevious &&   //2、 上一根收盘K线的长期均线的值 大于 上一根收盘K线的长期均线的值   即： 1,2表示两条均线交叉
                upAvg > upAvgPrevious &&            //3、当前收盘K线的长期均线的值  大于  当前收盘K线的短期均线的值       即：长期均线网上走
                klines.get(1).getClose() > downAvg &&     //4、当前收盘K线的收盘价高于短期均线的收盘价
                !KlineUtil.isUpperLead(klines.get(1),upperLeadFactor) &&  //5、当前收盘K线不能收长的上引线
                !KlineUtil.isUpperLead(klines.get(2),upperLeadFactor) &&  //6、当前收盘K线的上一个K线不能收上引线
                KlineUtil.getGain(klines.get(1))>-0.01 &&  //7、当前收盘K线跌幅不能大于1个点
                KlineUtil.getGain(klines.get(2))>-0.01 &&  //8、当前收盘K线的上一个K线跌幅不能大于1个点
                !( KlineUtil.getGain(klines.get(1))<0 &&  KlineUtil.getGain(klines.get(2))<0 &&  KlineUtil.getGain(klines.get(3))<0)  && //9、最近三根收盘的K线不能都是下跌
                1==1
                ) {
            if(avgUpDownFlagOrder == -1){
                buyOpen(symbol, contractType, leverRate, volume, futurePostV1);
            }
        }
        if(downAvg > klines.get(1).getClose()){  // 卖出条件： 1、当前收盘K线的收盘价 小于 当前收盘K线的短期均线的值
            if(avgUpDownFlagOrder == 1){
                sellClose(symbol, contractType, leverRate, volume, futurePostV1);
            }
        }
    }
    /**
     * 两天均线策略EOS
     */
    public static void towMaEOS()  throws Exception{
        String symbol = "EOS";//交易对
        String contractType = "quarter";//合约类型
        int upMa = 30;//建仓均线
        int downMa = 6;//平仓均线
        String period = "15min";//时间周期
        int leverRate = 20;//合约倍数
        int volume = 199;//每次买卖的张数
        double upperLeadFactor = 2.5;  //上引线的判断因子
        /**
         * get请求无需发送身份认证,通常用于获取行情，市场深度等公共信息
         */
        System.out.println("EOS 季度合约开始");
        String api_key = HbdmClient.api_key; // huobi申请的apiKey,API调试过程中有问题或者有疑问可反馈微信号shaoxiaofeng1118
        String secret_key = HbdmClient.secret_key; // huobi申请的secretKey
        String url_prex = HbdmClient.url_prex;//"https://api.hbdm.com";//火币api接口地址https://api.hbdm.com
        IHbdmRestApi futureGetV1 = new HbdmRestApiV1(url_prex);
        IHbdmRestApi futurePostV1 = new HbdmRestApiV1(url_prex, api_key, secret_key);
        initAvgUpDown(futurePostV1,symbol,contractType);
        logger.info("avgUpDownFlagOrder：" +avgUpDownFlagOrder);
        // 获取K线数据
        String historyKline = futureGetV1.futureMarketHistoryKline(symbol+"_CQ", period,(upMa+3)+"");
        logger.info("获取K线数据" + historyKline);
        JSONObject jsonObject = JSONObject.parseObject(historyKline);
        JSONArray jsonArray = jsonObject.getJSONArray("data");
        List<Kline> klines = jsonArray.toJavaList(Kline.class);
        KlineUtil.sort(klines);
        logger.info("K线排序,时间最大的排前面：" +JSONObject.toJSONString(klines));

        List<Kline> klinesUp = new ArrayList<>();
        for(int i=0;i<upMa;i++){
            klinesUp.add(klines.get(i+1));
        }
        double upAvg = KlineUtil.queryAvg(klines); //当前收盘K线的长期均线的值

        List<Kline> klinesDown = new ArrayList<>();
        for(int i=0;i<downMa;i++){
            klinesDown.add(klines.get(i+1));
        }
        double downAvg = KlineUtil.queryAvg(klinesDown);   //当前收盘K线的短期均线的值

        List<Kline> klinesUpPrevious = new ArrayList<>();
        for(int i=0;i<upMa;i++){
            klinesUpPrevious.add(klines.get(i+2));
        }
        double upAvgPrevious = KlineUtil.queryAvg(klinesUpPrevious);    //上一根收盘K线的长期均线的值

        List<Kline> klinesDownPrevious = new ArrayList<>();
        for(int i=0;i<downMa;i++){
            klinesDownPrevious.add(klines.get(i+2));
        }
        double downAvgPrevious = KlineUtil.queryAvg(klinesDownPrevious);  //上一根收盘K线的短期均线的值

        List<Kline> klinesDownThird = new ArrayList<>();
        for(int i=0;i<downMa;i++){
            klinesDownThird.add(klines.get(i+3));
        }
        double downAvgThird = KlineUtil.queryAvg(klinesDownThird);  //上上一根收盘K线的短期均线的值

        logger.info("均值upMA：" + upAvg);
        logger.info("均值downMA：" + downAvg);
        logger.info("上一个已收盘的K线：" + JSONObject.toJSONString(klines.get(1)));
        if(
                upAvg < downAvg  &&    //买入条件： 1、当前收盘K线的长期均线值 小于 短期均线的值
                        upAvg > upAvgPrevious &&            //2、当前收盘K线的长期均线的值  大于  当前收盘K线的长期均线的值       即：长期均线网上走
                        klines.get(1).getClose() > downAvg &&     //3、当前收盘K线的收盘价高于短期均线的收盘价
                        !KlineUtil.isUpperLead(klines.get(1),upperLeadFactor) &&  //4、当前收盘K线不能收长的上引线
                        !KlineUtil.isUpperLead(klines.get(2),upperLeadFactor) &&  //5、当前收盘K线的上一个K线不能收上引线
                        KlineUtil.getGain(klines.get(1))>-0.008 &&  //7、当前收盘K线跌幅不能大于0.8个点
                        KlineUtil.getGain(klines.get(2))>-0.008 &&  //8、当前收盘K线的上一个K线跌幅不能大于0.8个点
                        !KlineUtil.bigVolDown(klines.get(1),klines.get(2),klines.get(3)) &&   //9、下跌那根K线的量不能是最近三根K线的最大量
                        downAvg >downAvgPrevious && //10、短期均线翻上
                        !KlineUtil.twoDown(klines.get(1),klines.get(2),klines.get(3),downAvg,downAvgPrevious,downAvgThird) &&  //11、最近三根K线中不能有两根以上的K线下跌
                        1==1
                ) {
            if(avgUpDownFlagOrder == -1){
                buyOpen(symbol, contractType, leverRate, volume, futurePostV1);
            }
        }
        if(downAvg > klines.get(1).getClose()){  // 卖出条件： 1、当前收盘K线的收盘价 小于 当前收盘K线的短期均线的值
            if(avgUpDownFlagOrder == 1){
                sellClose(symbol, contractType, leverRate, volume, futurePostV1);
            }
        }
        System.out.println("EOS 季度合约结束");
    }
    /**
     * 卖出平仓
     * @param symbol
     * @param contractType
     * @param leverRate
     * @param volume
     * @param futurePostV1
     * @throws HttpException
     * @throws IOException
     */
    private static void sellClose(String symbol, String contractType, int leverRate, int volume, IHbdmRestApi futurePostV1) throws HttpException, IOException {
        String contractOrder = futurePostV1.futureContractOrder(symbol, contractType, "", "", "", volume+"",
                "sell", "close", leverRate+"", "opponent");
        logger.info("合约下单（卖出平仓）：" + contractOrder);
        String status = JSONObject.parseObject(contractOrder).getString("status");
        if("ok".equals(status)){
            avgUpDownFlagOrder = -1;
        }
    }

    /**
     *  买入开仓
     * @param symbol
     * @param contractType
     * @param leverRate
     * @param volume
     * @param futurePostV1
     * @throws HttpException
     * @throws IOException
     */
    private static void buyOpen(String symbol, String contractType, int leverRate, int volume, IHbdmRestApi futurePostV1) throws HttpException, IOException {
        String contractOrder = futurePostV1.futureContractOrder(symbol, contractType, "", "", "", volume+"",
                "buy", "open", leverRate+"", "opponent");
        logger.info("合约下单（买入开仓）：" + contractOrder);
        String status = JSONObject.parseObject(contractOrder).getString("status");
        if("ok".equals(status)){
            avgUpDownFlagOrder =1;
        }
    }
}
